こんにちわ。Mr.Xです。
最近vulsを作った方にこのblogが捕捉されたようで、大変恐縮であります。
元ネタは、あなたの記事です。
さて、
前回の記事からかなり時間がかかったのだけど、それには下記のような理由がある。
・Azure Functionsはまだプレビュー。資料は充実しているとは言えない。
・C#は書いたことがない。なので多少は書いたことがあるJavaScriptに切り替えた。
・WebAppsでの構築経験もない。
・その他淡々とハマり続けた。
という感じで勢いだけで始めた無慈悲な結果だ。ただ、こうして記事を書いている、ということは、思ってたことは実現できた、というわけだ。
前回ではvulsの結果をAzureのblobストレージに投入するところまでができた。なので、今回は、Azure Functions を中心に解説していく。
1.Functionsでなにやるんだったっけ?
Blobのアップデートイベントをトリガとして、VMにタグ付けをする。
Blobに指定のファイルが作られたら、というほうが正確か。なお、一度イベントとして捕捉されたファイルは、消して再アップしないとやり直しはできない。
テストにはAzureCLIとStorageExprolerを利用した。
2.捕捉できるトリガ。
こちらをご覧ください。
https://azure.microsoft.com/ja-jp/documentation/articles/functions-triggers-bindings/
3.FunctionsからAPIにアクセスするには、アプリの登録をしたほうがいい。
自然に考えれば、自分に結びついているWebアプリをポータルのGUIで編集し、動作させるのだから、いちいちアクセスのためのキーを用意したり、というのは違和感があるが、そのアプローチでは調べてないので、一般的な方法を使った。
3-1.ADへの登録
ドキュメントはこれ。というのがなかったので、
こちらを参考にしてほしい。本記事では超重要。
GUIでやる場合は、旧ポータルからAzureActiveDirectoryを利用して、アプリの登録を行う。その際、指定を求められるURIやURLは適当で大丈夫。
3-2.Powershellを使ってロールの追加
PS> Get-AzureRmADApplication -DisplayNameStartWith hoge
DisplayStartNameはアプリケーション名が何から始まるかをいれれば、前方一致で見つけてくれる。
なお、次の工程のロール追加で戻り値を利用するので、$aad_app とかの変数に格納しておこう。
ロールの追加は旧ポータルからはできないので、PowerShellでやる。
PS> $aad_app = Get-AzureRmADApplication -DisplayNameStartWith hoge
PS> New-AzureRmRoleAssignment -RoleDefinitionName “Owner” -ServicePrincipalName $aad_app.ApplicationId
を実行する。正直Ownerである必要はないが、今回程度のお試しならOwnerってしとけば大丈夫。
4.Functionsでのコーディングと、環境の準備
今回の例では、”ms-rest-azure”と”azure-arm-compute”の二つのパッケージを使う。
kuduにアクセスするには、Functoin Appを作成した後に、
https://アプリケーション名.scm.azurewebsites.net/
でアクセスする。
4-1.kudu画面でのnpmによるパッケージインストール。
kuduの画面を利用して、デバッグにPowerShellを起動し、home/www/site/[hoge]内でPS> npm install
PS> npm install ms-rest-azure
PS> npm install azure-arm-compute
Functionsのアプリケーションのファイル(index.js)があるところで実行する。
なお、package.jsonがそこにないことでWARNINGが出まくるしERRORとかかいてあるけど、大丈夫だった。
4-2.FunctionsのUIでのコーディング
作成したFunction Appの画面ではこのような初期画面が出る。
今回のケースでは、上の画面の左側にある”New Function”をクリックし、下図のように表示されるテンプレートの “BlobTrigger Node”を利用した。
コードはこれ。
module.exports = function (context, myBlob) { context.log('--- Start!'); var ServerInfo = String(myBlob.ServerName).split('_'); context.log('ResourceGroup: ', ServerInfo[0]); context.log('VMName: ', ServerInfo[1]); var HighestScore = myBlob.KnownCves[0].CveDetail.Nvd.Score; context.log('HighestScore: ', HighestScore); var Level = "unKnown"; if( 7 <= HighestScore ){ Level = "High"; }else if( 4 <= HighestScore ){ Level = "Middle"; }else if( 0 <= HighestScore ){ Level = "Low"; } context.log('Level: ', Level); // Azure API Config. var clientId = '[ClientID]'; var clientSecret = '[clientSecret]'; var tenant = 'mytenant.onmicrosoft.com'; var subscriptionId = '[subscriptionID]'; var vm_Location = 'japanwest'; var ms_restAzure = require('ms-rest-azure'); ms_restAzure.loginWithServicePrincipalSecret(clientId, clientSecret, tenant, function(err, credentials) { if (err){ context.log('Error: ', err); }else{ var az_computeClient = require('azure-arm-compute'); var client = new az_computeClient(credentials, subscriptionId); var param = { location: vm_Location, tags : { vuls : Level } }; client.virtualMachines.createOrUpdate(ServerInfo[0], ServerInfo[1], param, function (err, result) { if(err){ context.log('Error: ', err); }else{ context.log('--Success'); } }); } context.log("--- function Done."); context.done(); }); };
C#に挫折するところから始まり、npm、というかnodeがおかしい?というようなトラブルを経てなんとか完成。
「テナントID」がなんのことかわからずかなり苦労したが、要は、
AADドメイン名.onmicrosoft.com のことだった。
また日を改めて、じっくり考えることにする。
今度まとめます。いろいろありました。
・APIの利用手順としてこれ使いました。
記事内では Get-AzureRmAdApplicationはない、ということだが、いまはある。
なので、旧ポータルでの登録からの、RoleAssignが可能になっている。
・AzureAPI(node)
https://github.com/Azure/azure-sdk-for-node/blob/master/Documentation/Authentication.md
ここでAPIに対するアクセスで、トークンを利用した場合の基本形を確認できる。
・Azure arm computeのドキュメント
http://azure.github.io/azure-sdk-for-node/azure-arm-compute/latest/
https://github.com/Azure/azure-sdk-for-node/blob/master/examples/ARM/compute/vm-sample.js
今日はここまで。